package ruc.MongoDB.read;

import com.mongodb.client.MongoCollection;
import org.bson.Document;
import ruc.Consts.constant;
import ruc.utils.IOUtils;
import ruc.MongoDB.MongoDB_Common;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicLong;

public class MongoDB_ConcurrentRead {
    private int bound, port;
    private String IP, dbName, tbName;

    public MongoDB_ConcurrentRead(String IP, int port, String dbName, String tbName,int bound) {
        this.IP = IP;
        this.port = port;
        this.dbName = dbName;
        this.tbName = tbName;
        this.bound = bound;
    }

    public void conRead(int[] client) throws InterruptedException {
        Random ran = new Random();
        MongoCollection<Document> collection = MongoDB_Common.GetMongoCollection(IP, port, dbName, tbName);
        for(int i = 0; i < client.length; i++) {
            CountDownLatch CDL = new CountDownLatch(client[i]);
            AtomicLong AL = new AtomicLong(0);
            for(int k = 0; k < client[i]; k++) {
                new Thread(() ->{
                    long startTime = System.nanoTime();
                    collection.find().limit(ran.nextInt(bound)).skip(ran.nextInt(bound));
                    long costTime = (System.nanoTime() - startTime);
                    AL.addAndGet(costTime); // 在mongo中由于读写速度快，转成ms会有较大的精度损失，直接使用ns
                    CDL.countDown();
                }).start();
            }

            CDL.await();
            System.out.printf("[TSBench-D] >>>>> [MongoDB_ConcurrentRead] ThreadNum:%d, response time : %d ns>>>>> \n", client[i], AL.longValue());
            IOUtils.WriteData(constant.GetWriteFilePath("MongoDB", "concurrentRead"),
                    new String[]{String.valueOf(client[i]), AL.longValue()+"ns"});
        }
    }

    public static void main(String[] args) throws InterruptedException {
        MongoDB_ConcurrentRead db = new MongoDB_ConcurrentRead(constant.IP, constant.MongoDB_port, constant.dbName, constant.Concurrent_tbName, constant.bound);
        db.conRead(constant.ConcurrentReadThreadNum);
    }
}
